import { Types } from "stay";
type ST_setValue = (key: string, value: unknown) => string;
type ST_deleteValue = (key: string) => string;

type ST_addValueChangeListener = (
  name: string,
  callback: Types.Vcl.cbFunction,
) => number;

type ST_removeValueChangeListener = (
  id: ReturnType<ST_addValueChangeListener>,
) => void;

type ST_getResourceURL = (name: string) => string | undefined;
type ST_getResourceText = (name: string) => string | undefined;

type ST_openInTab = (
  url: string,
  options?: Types.OpenTab.Option,
) => Types.OpenTab.Result;

type ST_openInTab_P = (
  url: string,
  options?: Types.OpenTab.Option,
) => Promise<Types.OpenTab.PromiseResult>;

type ST_registerMenuCommand = (
  caption: string,
  fn: Types.Menu.Callback,
  accessKey?: string,
) => string;
type ST_registerMenuCommand_P = (
  caption: string,
  fn: () => void | Promise<void>,
  accessKey?: string,
) => string;
type ST_unregisterMenuCommand = (
  id: ReturnType<ST_registerMenuCommand>,
) => void;

type ST_xmlhttpRequest = (details: Types.Xhr.Details) => CM_Types.Xhr.Return;
type ST_download_D = (details: Types.Download.Details) => void;
type ST_download_U = (url: string, name: string) => void;

type ST_addStyle = (css: string) => string;

type ST_Notification_O = (
  options: Types.Notification.Option,
  ondone?: () => void,
) => void;

type ST_Notification_T = (
  text: Types.Notification.Option["text"],
  title?: Types.Notification.Option["title"],
  image?: Types.Notification.Option["image"],
  onclick?: () => void,
) => void;

type ST_log = (message: string) => Promise<void>;

interface ST_ScriptInfo {
  readonly description?: string;
  readonly excludes: string[];
  readonly includes: string[];
  readonly matches: string[];
  readonly name: string;
  readonly namespace: string;
  readonly resources: Record<string, string>;
  readonly scriptMetaStr: string;
  readonly version: string;
}

interface ST_Info {
  readonly script: ST_ScriptInfo;
  readonly scriptHandler: "Stay";
  readonly version: string;
}

interface ST_Object {
  getValue: Promisize<CM_getValue>;
  setValue: Promisize<ST_setValue>;
  listValues: Promisize<CM_listValues>;
  deleteValue: Promisize<ST_deleteValue>;
  addValueChangeListener: Promisize<ST_addValueChangeListener>;
  removeValueChangeListener: Promisize<ST_removeValueChangeListener>;
  getResourceUrl: Promisize<ST_getResourceURL>;
  getResourceURL: Promisize<ST_getResourceURL>;
  getResourceText: Promisize<ST_getResourceText>;
  openInTab: ST_openInTab_P;
  registerMenuCommand: ST_registerMenuCommand_P;
  unregisterMenuCommand: ST_unregisterMenuCommand;
  xmlHttpRequest: ST_xmlhttpRequest;
  download: ST_download_D & ST_download_U;
  addStyle: Promisize<ST_addStyle>;
  notification: ST_Notification_O & ST_Notification_T;
  readonly info: ST_Info;
}

declare module "stay" {
  export const GM: ST_Object;
  export const GM_getValue: CM_getValue;
  export const GM_setValue: ST_setValue;
  export const GM_listValues: CM_listValues;
  export const GM_deleteValue: ST_deleteValue;
  export const GM_addValueChangeListener: ST_addValueChangeListener;
  export const GM_removeValueChangeListener: ST_removeValueChangeListener;
  export const GM_getResourceURL: ST_getResourceURL;
  export const GM_getResourceText: ST_getResourceText;
  export const GM_openInTab: ST_openInTab;
  export const GM_registerMenuCommand: ST_registerMenuCommand;
  export const GM_unregisterMenuCommand: ST_unregisterMenuCommand;
  export const GM_xmlhttpRequest: ST_xmlhttpRequest;
  export const GM_download: ST_download_D & ST_download_U;
  export const GM_addStyle: ST_addStyle;
  export const GM_notification: ST_Notification_O & ST_Notification_T;
  export const GM_log: ST_log;
  export const GM_info: ST_Info;
  export let unsafeWindow: unsafeWindow;
}
